#include <string.h> 
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>

#include "rngs.h"
#include "dominion.h" 
#include "dominion_helpers.h"

#define TESTS 10000

int main (int argc, char *argv[])
{
	int i;
	int j;
	int p;
	int whoseTurn;
	int seed;
	int numPlayers;
	int handCount;
	int numActions;
	int bonus;
	int deckCount;
	int discardCount;
	int numBuys;
	int coins;
	int playedCardCount;
	int phase;
	int outpostPlayed;
	int outpostTurn;
	int cardPosition;
	int firstTreasurePosition;
	int secondTreasurePosition;
	int randomTreasure;
	int randomNum;
	int numFails = 0;
	int numCoins;
	
	int k[10] = {adventurer, council_room, feast, gardens, mine
	             , remodel, smithy, village, baron, great_hall};
	struct gameState G;

	srand(time(NULL));

	for (i = 0; i < TESTS; i++) {
		//initialize the game 
		seed = rand() % 100000000 + 1; //seed must be positive less then 9 dig 
		numPlayers = rand() % 3 + 2; // 2-4
		memset(&G, 23, sizeof(struct gameState));
		initializeGame(numPlayers, k, seed, &G);

		//setup for each player
		for (p = 0; p < numPlayers; p++) {
			G.handCount[p] = rand() % MAX_HAND;
			for (j = 0; j < G.handCount[p]; j++)
				G.hand[p][j] = k[(rand() % 10)]; //rand card 0-10 from k[] 
			G.deckCount[p] = rand() % MAX_DECK + 2; //needed for adventurer
			for (j = 0; j < G.deckCount[p]; j++)
				G.deck[p][j] = k[(rand() % 10)]; //rand card 0-10 from k[]  
			G.discardCount[p] = rand() % MAX_DECK; 
			for (j = 0; j < G.discardCount[p]; j++)
				G.discard[p][j] = k[(rand() % 10)]; //rand card 0-10 from k[]  
		
		}

		//current player setup
		whoseTurn = rand() % numPlayers;
		G.whoseTurn = whoseTurn;
		numActions = rand() % 10 + 1; //needs to be at least one
		G.numActions = numActions;
		numBuys = rand() % 10 + 1; //needs to be at least one
		G.numBuys = numBuys;
		coins = rand() % 10;
		G.coins = coins; 
		
		handCount = G.handCount[whoseTurn];
		deckCount = G.deckCount[whoseTurn];
		discardCount = G.discardCount[whoseTurn];

		//unimplemented: phase, outpost, supply, embargo
		//(will possibly need for future cards)

		G.playedCardCount = rand() % MAX_DECK;
		for (j = 0; j < G.playedCardCount; j++)
			G.playedCards[j] = k[(rand() % 10)]; //rand card 0-10

		//NOT NEEDED, caused a bug for       % 0
		//insert card randomly into hand
		//cardPosition = rand() % G.handCount[whoseTurn];
		//G.hand[whoseTurn][cardPosition] = adventurer; //change for different

		//for adventurer you need at least two treasure cards in deck
		//else possibly infinite loop?
		randomNum = rand() % 3;
		if (randomNum == 0)
			randomTreasure = copper;
		else if (randomNum == 1)
			randomTreasure = silver;
		else 
			randomTreasure = gold;
		firstTreasurePosition = rand() % G.deckCount[whoseTurn];
		G.deck[whoseTurn][firstTreasurePosition] = randomTreasure;
		//second treasure 
		do {
			secondTreasurePosition = rand() % G.deckCount[whoseTurn];
		} while (firstTreasurePosition == secondTreasurePosition);
		randomNum = rand() % 3;
		if (randomNum == 0)
			randomTreasure = copper;
		else if (randomNum == 1)
			randomTreasure = silver;
		else 
			randomTreasure = gold;
		G.deck[whoseTurn][secondTreasurePosition] = randomTreasure;
			
		//save coins
		updateCoins(whoseTurn, &G, 0);
		numCoins = G.coins;
		
		//playcard
		if (cardEffect(adventurer, 0, 0, 0, &G, cardPosition, NULL) == -1) {
			printf("FAIL: cardEffect() returned a failure\n");
			numFails++;
			printf("FAIL STATE: Seed:%d numPlayers:%d whoseTurn:%d handCount:%d deckCount:%d cardPosition:%d\n", seed, numPlayers, whoseTurn, handCount, deckCount, cardPosition);
		}

		//test if you have 2 extra cards 
		if (G.handCount[whoseTurn] == (handCount + 2)) {
			//printf("PASS: Correct number of cards in hand\n");
		}
		else {
			printf("FAIL: Incorrect number of cards in hand\n");
			numFails++;
			printf("FAIL STATE: Seed:%d numPlayers:%d whoseTurn:%d handCount:%d deckCount:%d cardPosition:%d\n", seed, numPlayers, whoseTurn, handCount, deckCount, cardPosition);
		}

		//test you have more coins 
		updateCoins(whoseTurn, &G, 0);
		if (G.coins > numCoins) {
			//printf("PASS: Coins correctly increased\n");
		}
		else {
			printf("FAIL: Coins did not increase\n");
			numFails++;
			printf("FAIL STATE: Seed:%d numPlayers:%d whoseTurn:%d handCount:%d deckCount:%d cardPosition:%d\n", seed, numPlayers, whoseTurn, handCount, deckCount, cardPosition);
		}
	}

	if (numFails == 0)
		printf("ALL TESTS PASSED\n");
	else {
		printf("%d TESTS FAILED\n", numFails);
	}

	return 0;
}
